package snu.bi.MSAgent.ActRecog;

import java.io.*;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Observable;
import java.util.Observer;
import java.util.Vector;

import snu.bi.MSAgent.ExerActivity;
import snu.bi.MSAgent.MSAgentActivity;
import snu.bi.MSAgent.DB.MSADBHandler;

import libsvm.svm;
import libsvm.svm_model;

import android.app.Activity;
import android.app.ActivityManager;
import android.app.Service;
import android.content.ContentValues;
import android.content.Intent;
import android.hardware.*;
import android.net.Uri;
import android.os.Environment;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;


public class ActionService extends Service implements Runnable{
	public static final String MY_ACTION = "snu.bi.MSAgent.ActRecog.ActionService.intent.action.MY_ACTION";
        private int startId;
        private Handler handler;
        private boolean isRunning;
        private static final int TIMER_PERIOD = 2000;
        private static final int COUNT = 100;
        private int counter;
        
        private SensorManager sm;
        private SensorEventListener accListener;
        private Sensor accSensor;
        
        private int cnt = 0;
        private double[] Re;
        private double[] Im;
        private double[] ReFFT;
        private double[] ImFFT;
        FFT fft;
        private static final int FFT_SIZE = 8;
        
        private String []arg;
        svm_model model;
        
        private MSADBHandler hDB;
        double val;
        
        public final static int ACTION_RUN = -1;
        public final static int ACTION_WALK = 1;
        public final static int ACTION_STAY = 0;
        
        /*############### kailieu ####################*/
        Intent intent = null;
        private static ActionService sInstance = null;
        private Vector<Observer> obs = null;
        
        public void onCreate(Intent i){
        	this.intent = i;
        	this.onCreate();
        }
        
        public static ActionService getInstance(){
        	return ActionService.sInstance;
        }
        
        public void setObserver(Observer activity){
        	this.obs.add(activity);
        }
        
        private void updateAll(Object arg){
        	Observer ob = null;
        	if ((ob = MSAgentActivity.getInstance()) != null){
        		ob.update(null, arg);
        	}
        	if ((ob = ExerActivity.getInstance()) != null){
        		ob.update(null, arg);
        	}
        }
        
        /*############################################*/
                
        public void onCreate(){
                super.onCreate();
                ActionService.sInstance = this;
                handler = new Handler();
                isRunning = false;
                hDB = MSADBHandler.open(getApplicationContext());
                counter = 0;
                
                sm = (SensorManager)getSystemService(SENSOR_SERVICE);
                accSensor = sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
                accListener = new AccListener();
                Re = new double[FFT_SIZE];
                Im = new double[FFT_SIZE];
                fft = new FFT(FFT_SIZE);
                arg = new String[3];
                arg[0] = "";
                arg[1] = Environment.getExternalStorageDirectory().getAbsolutePath()+"/data/snu.bi.MSAgent/model2.txt";
                arg[2] = Environment.getExternalStorageDirectory().getAbsolutePath()+"/data/snu.bi.MSAgent/dummy.txt";
                try {
//                	ObjectInputStream in = new ObjectInputStream(new FileInputStream(arg[1]));
//                	model = (svm_model)in.readObject();
                	model = svm.svm_load_model(arg[1]);

					
				} catch (Exception e) {
					e.printStackTrace();
				}
                Log.i("svm_test", "Svc Created");
                
        }
        public int onStartCommand(Intent intent, int flags, int startId){
                super.onStart(intent, startId);
                this.startId = startId;
                Log.i("svm_test", "OK?");
                sm.registerListener(accListener, accSensor, SensorManager.SENSOR_DELAY_NORMAL);
                if(!isRunning){
                        handler.postDelayed(this, TIMER_PERIOD);
                        isRunning = true;
                }
                return START_STICKY;
        }
        

        public void onDestroy(){
                isRunning = false;
                sm.unregisterListener(accListener);
                super.onDestroy();
        }
        
        @Override
        public IBinder onBind(Intent arg0) {
                // TODO Auto-generated method stub
                return null;
        }

        public void run() {
        	Log.i("svm_test", "run");
                if(!isRunning){
                        return;
                }/*else if(--counter <=0){
                        stopSelf(startId);
                }*/else{
                		String str = "+1";
                        ReFFT = Re.clone();
                        ImFFT = Im.clone();
                        Log.i("svm_test", Arrays.toString(ReFFT));
                        fft.fft(ReFFT, ImFFT);
                        for(int i=1; i<=FFT_SIZE; i++){
                        	str += " "+i+":"+ReFFT[i-1];
                        }
                        for(int i=1; i<=FFT_SIZE; i++){
                        	str += " "+(i+FFT_SIZE)+":"+ImFFT[i-1];
                        }
                        arg[0] = str;
                        
                        try {
                        	
                            val = svm_predict.run(arg, model);
                            double meanAcc = 0;
                            for(int i=0; i<FFT_SIZE; i++){
                            	meanAcc += Re[i];
                            }meanAcc /= FFT_SIZE;
//                            Intent intent = new Intent();
//                            intent.setAction(MY_ACTION);
                            if(Math.abs(meanAcc-9.8) < 1){
//                            	Toast.makeText(this, "Stay", Toast.LENGTH_SHORT).show();
//                            	intent.putExtra("CURR_ACT", "Stay");
//                            	val = 0;
                            	
                            	/*################# kailieu*/
                            	this.updateAll("Stay");
                            	
                            }else if(Math.abs(meanAcc-9.8) < 3){
//                            	Toast.makeText(this, "Walk", Toast.LENGTH_SHORT).show();
//                            	intent.putExtra("CURR_ACT", "Walk");
                            	
                            	/* kailieu */
                            	this.updateAll("Walk");
                            	
                            }else{
//                            	Toast.makeText(this, "Run", Toast.LENGTH_SHORT).show();
//                            	intent.putExtra("CURR_ACT", "Run");
                            	
                            	/* kailieu */
                            	this.updateAll("Run");
                            }
//                            sendBroadcast(intent);
                        	Log.i("test", Double.toString(val)+", "+Double.toString(meanAcc));
                        	counter++;                        	
                        		
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
              /*          if(Re[0] > 12){
                        	Log.i("test", "Run");
                        	Toast.makeText(this, "Run", Toast.LENGTH_SHORT).show();
                        }else{
                        	Log.i("test", "Walk");
                        	Toast.makeText(this, "Walk", Toast.LENGTH_SHORT).show();
                        }*/
                        cnt = 0;                        
                        if(counter >= 20){
                        	counter = 0;
                        	
                        	ContentValues newValues = new ContentValues();
            				newValues.put("time", new Date().getTime());
            				newValues.put("act_type", val);
            				hDB.insert("excer_table", null, newValues);
            				
                        }
                        handler.postDelayed(this, TIMER_PERIOD);
                }
        }
        
        private class AccListener implements SensorEventListener{

                public void onAccuracyChanged(Sensor arg0, int arg1) {
                }

                public void onSensorChanged(SensorEvent event) {
                        double acc = Math.sqrt(
                                        event.values[0]*event.values[0]+
                                        event.values[1]*event.values[1]+
                                        event.values[2]*event.values[2]);
                        if(cnt < FFT_SIZE){
                                Re[cnt] = acc;
                                Im[cnt] = 0;
                                cnt++;
                        }
                }
        }
        
}